#include <iostream>
#include <array>
#include <tuple>
#include <string>
#include <sstream>

#include <type_traits> 
#include <iostream>
using namespace std;

/*
参考TraitsLearn4

去掉无用传入参数问题

*/
namespace TraitsLearn5 {

    /*假设有一个未知类*/
    template <class T>
    struct unknown_class  {
        typedef T type;
    };
   
    /*先定义一些tag*/
    struct A :unknown_class<A> {
        float a;
    };
    struct B : unknown_class<B> {
        float b;
    }; 

    /*获取到返回类型*/
    template <class T>
    struct unknown_class_traits {
        typedef typename T::type type;
    };

    /*特性萃取器 —— 针对原生指针*/
    template <class T>
    struct unknown_class_traits<T*> {
        typedef T type;
    };

    /*特性萃取器 —— 针对指向常数*/
    template <class T>
    struct unknown_class_traits<const T*> {
        typedef const T type;
    };


 
    template <typename T>
    inline  typename unknown_class_traits<T>::type
        __func(T u) {
        char* ptr;
        uintptr_t number = (uintptr_t)ptr;
        cout << "use origin ptr" << endl;
        cout << "u=" << u << endl;
        cout << "*u=" << *u << endl;
        return *u * 2;
    }
    template <>
    inline A __func(A u) {
        A a1=u;
        cout << "u.a="<<u.a << endl;
        a1.a += 10;
        cout << "use A flag" << endl;
        return a1;
    }
    template <>
    inline B __func(B u) {
        cout << "u.b=" << u.b << endl;
        cout << "use B flag" << endl;
        return B();
    }

 
    template <class T>
    inline typename unknown_class_traits<T>::type
        func(T u) {
        typedef typename unknown_class_traits<T>::type type;
        cout << " \t is_same<T, type>  " << std::is_same<T, type>::value << endl;
        // A、B、int *, float* 相同逻辑代码，在func里实现。
        //不同的逻辑代码，放在各自的__func里实现
        //场景： 抽象代数的乘法实现  矩阵、
       return  __func(u);
        
    }

    int main() {

        A a;
        B b;

        int value = 1;
    //    int vf = func(value);  //int没有type   int *可以解析为 struct unknown_class_traits<T*>
        int* p = &value;

        float f =2;
        float* pFloat = &f;

        a.a = 20;
        A v1 = func(a);
        cout << " v1.a=" << v1.a << endl;
       
        b.b = 30;
        B v2 = func(b);
        cout << " v2=" << v2.b << endl;

        int v3 = func(p);
        cout << " v3=" << v3 << endl;
       float v4 = func(pFloat);
       cout << " v4=" << v4 << endl;
       
       float v5 = func(&f);
       cout << " v5=" << v5 << endl;

        return 0;
    }
   
}
